<!--
  高级导出模态框

  用法：
  <qm-export-modal
    v-model="exportModalVisible"
    @export-modal-close="exportModalVisible = false"
    :exportConfig="finalExportConfig"
    :seniorExportUrl="seniorExportUrl"
  >
  </qm-export-modal>

  参数说明：
  exportModalVisible：是否显示高级导出模态框
  seniorExportUrl: 导出接口地址【必须传】
  exportConfig: {
    filename：文件名，默认为"导出_20210915150452"，
    type：文件类型，默认为"xlsx"(暂时只支持xlsx)
    columns: 选择字段，【必须传】。[{
      field: title
    }]
  }
  其余参数请参阅代码props

  事件说明：
  export-modal-close：关闭回调
  submit-modal：提交回调
  cancel-modal：取消回调
  
-->
<template>
  <vxe-modal
    ref="exportModalRef"
    v-model="visible"
    v-bind="finalModalOptions"
    @close="closeExportModal"
  >
    <el-form
      :ref="formRefs"
      :model="exportFormModel"
      v-bind="finalExportFormOptions"
      :rules="exportFormRules"
      class="export-form"
    >
      <el-form-item label="文件名" prop="filename">
        <el-input
          v-model="exportFormModel.filename"
          placeholder="请输入文件名"
          clearable
        ></el-input>
      </el-form-item>
      <el-form-item label="保存类型" prop="type">
        <el-select
          v-model="exportFormModel.type"
          placeholder="请选择保存类型"
          clearable
        >
          <el-option
            v-for="item in fileTypes"
            :key="item.key"
            :label="item.label"
            :value="item.key"
          >
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="选择字段" prop="columns">
        <el-empty
          v-if="!(exportConfigColumns.length > 0)"
          description="字段不能为空喔"
        ></el-empty>
        <div class="field-content" v-else>
          <el-checkbox
            class="all-checkbox"
            :indeterminate="isIndeterminate"
            v-model="checkAllColumns"
            @change="handleCheckAllColumnsChange"
          >
            全部字段
          </el-checkbox>
          <el-checkbox-group
            class="field-group"
            v-model="exportFormModel.columns"
            @change="handleCheckedColumnsChange"
          >
            <el-checkbox
              v-for="column in exportConfigColumns"
              :label="column.field"
              :key="column.field"
            >
              {{ column.title }}
            </el-checkbox>
          </el-checkbox-group>
        </div>
      </el-form-item>
    </el-form>
    <template v-slot:footer v-if="showFooter">
      <slot name="footer">
        <el-row>
          <el-button
            type="primary"
            :loading="saveLoading"
            @click="submitModal"
            icon="el-icon-circle-check"
          >
            {{ textMap.export || "导 出" }}
          </el-button>
          <el-button @click="cancelModal" icon="el-icon-circle-close">
            {{ textMap.cancel || "取 消" }}
          </el-button>
        </el-row>
      </slot>
    </template>
  </vxe-modal>
</template>

<script>
import lodash from "lodash";

const DEFAULT_FILE_TYPE = "xlsx";

export default {
  name: "qm-export-modal",
  props: {
    // 一些按钮的默认文字
    textMap: {
      type: Object,
      default: () => {
        return {
          export: "导 出",
          cancel: "取 消"
        };
      }
    },
    value: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: "高级导出",
      required: false
    },
    width: {
      type: Number | String,
      default: 660
    },
    height: {
      type: Number | String,
      default: 550
    },
    resize: {
      type: Boolean,
      default: true
    },
    showFooter: {
      type: Boolean,
      default: true
    },
    // 导出模态框属性配置，请参考vxe-table 3.x版本文档：https://xuliangzhan_admin.gitee.io/vxe-table/#/modal/api
    modalOptions: {
      type: Object,
      default: () => {}
    },
    // 表单的一些属性配置，请参考ElementUI 2.x版本文档：https://element.eleme.cn/#/zh-CN/component/form
    formOptions: {
      type: Object,
      default: () => {}
    },
    // 表单的ref值，用于表单校验
    formRefs: {
      type: String,
      default: "exportFormRef"
    },
    showFormVerifyErrorNotify: {
      type: Boolean,
      default: false
    },
    // 高级导出接口地址
    seniorExportUrl: {
      type: String,
      required: true
    },
    /**
     exportConfig: {
       filename：文件名，默认为"导出_20210915150452"，
       type：文件类型，默认为"xlsx"(暂时只支持xlsx)
       columns: 选择字段，必须。[{
         field: xxx,
         title: xxx
       }]
     }
     */
    exportConfig: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      visible: this.value,
      loading: false,
      exportFormModel: {
        filename: undefined,
        type: undefined,
        columns: [] // ['field']
      },
      exportFormRules: {
        type: { required: true, message: "请选择文件类型", trigger: "change" },
        columns: {
          type: "array",
          required: true,
          message: "请至少选择一个字段",
          trigger: "change"
        }
      },
      fileTypes: [{ key: "xlsx", label: "Excel 工作簿(*.xlsx)" }],
      checkAllColumns: true,
      saveLoading: false,
      isIndeterminate: true
    };
  },
  computed: {
    finalModalOptions() {
      return lodash.extend(
        {
          title: this.title,
          width: this.width,
          height: this.height,
          resize: this.resize,
          showFooter: this.showFooter,
          loading: this.loading,
          showZoom: true,
          destroyOnClose: true
        },
        this.modalOptions
      );
    },
    finalExportFormOptions() {
      return lodash.extend(
        {
          labelWidth: "180px"
        },
        this.formOptions
      );
    },
    /**
     * 获取导出配置-可选字段。如果没配置返回[]
     */
    exportConfigColumns() {
      return this.exportConfig && Array.isArray(this.exportConfig.columns)
        ? this.exportConfig.columns
        : [];
    },
    formModelColumns() {
      return this.exportFormModel && Array.isArray(this.exportFormModel.columns)
        ? this.exportFormModel.columns
        : [];
    }
  },
  watch: {
    value(visible) {
      this.loading = true;
      if (this.visible != visible) {
        this.visible = visible;
      }
      if (visible) {
        this.checkExportConfigData();
        this.setExportFormModel();
      }
      this.loading = false;
    }
  },
  created() {},
  mounted() {},
  methods: {
    checkExportConfigData() {
      if (this.exportConfigColumns.length <= 0) {
        this.msgError("请配置exportConfig.columns属性");
      }
    },
    setExportFormModel() {
      const { filename, type, columns } = this.exportConfig;
      this.exportFormModel = {
        filename: filename,
        type: type ? type : DEFAULT_FILE_TYPE,
        columns: this.getColumnsFields(columns)
      };
    },
    getColumnsFields(columns) {
      return Array.isArray(columns)
        ? columns.map(column => {
            return column.field;
          })
        : [];
    },
    handleCheckAllColumnsChange(checkAll) {
      this.exportFormModel.columns = checkAll
        ? this.getColumnsFields(this.exportConfigColumns)
        : [];
      this.isIndeterminate = false;
    },
    handleCheckedColumnsChange(value) {
      let checkedCount = value.length;
      let columnCount = this.exportConfigColumns.length;
      this.checkAllColumns = checkedCount === columnCount;
      this.isIndeterminate = checkedCount > 0 && checkedCount < columnCount;
    },
    submitModal() {
      this.validate()
        .then(valid => {
          if (valid) {
            this.saveLoading = true;
            try {
              this.excelExport();
              this.$emit("submit-modal");
              this.$emit("export-modal-close");
            } catch (error) {
              this.msgError(error);
            } finally {
              this.saveLoading = false;
            }
          }
        })
        .catch(err => {
          console.error("表单校验不通过，异常信息：", err);
          if (this.showFormVerifyErrorNotify) {
            this.notifyError("表单检验不通过，请检查表单");
          }
        });
    },
    validate() {
      return this.$refs[this.formRefs].validate();
    },
    excelExport() {
      const exportFormModel = lodash.extend({}, this.exportFormModel);
      const exportConfigColumns = this.exportConfigColumns;
      const { filename, type, columns } = exportFormModel;
      if (!(type && Array.isArray(columns) && columns.length > 0)) {
        throw new Error("表单检验不通过，请检查表单");
      }
      const selectFieldMap = new Map();
      columns.forEach(item => {
        selectFieldMap.set(item, item);
      });
      const formMap = {};
      exportConfigColumns.forEach(item => {
        const column = selectFieldMap.get(item.field);
        if (column) {
          formMap[item.field] = item.title;
        }
      });
      const postfix = "." + type;
      const name = filename
        ? filename
        : window.formatter.formatDate(new Date(), "yyyyMMddhhmmsss");
      window.location.href = `${process.env.VUE_APP_SERVER}${
        this.seniorExportUrl
      }?jsonStr=${encodeURIComponent(
        JSON.stringify(formMap)
      )}&postfix=${encodeURIComponent(postfix)}&filename=${name}`;
    },
    cancelModal() {
      this.$emit("cancel-modal");
      this.$emit("export-modal-close");
    },
    closeExportModal() {
      this.$emit("export-modal-close");
    }
  }
};
</script>

<style scoped>
.el-form-item__content div:first-child {
  width: 80%;
}
.field-content {
  display: flex;
  flex-flow: column nowrap;
  height: 250px;
  border: 1px solid #dcdfe6;
  margin: 3px 0;
  border-radius: 4px;
}
.all-checkbox {
  padding: 0 12px;
  font-weight: 700;
  border-bottom: 1px solid #e8eaec;
  background-color: #f8f8f9;
}
.field-group {
  width: 100%;
  display: flex;
  flex-flow: column nowrap;
  overflow: auto;
  padding: 0 12px;
}
.export-form >>> .el-form-item__error {
  line-height: 0.5;
  padding-top: 0;
}
</style>
